package org.opens.javaskill.design;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ProxyPattern {

    public static void main(String[] args) {
        Request request = new Request();
        RequestProxy requestProxy = new RequestProxy(request);

        System.out.println(getData(request, "1 or 1 = 1"));
        System.out.println(getData(requestProxy, "1 or 1 = 1"));
    }

    /**
     * 说明:
     *      1. 这个方法模拟使用到MyHttpRequest接口实现类的地方, 搭配代理模式可以实现新增一个实现类而不需要改动老代码进行升级.
     *          - 这就是多态的好处.
     */
    public static List<String> getData(MyHttpRequest request, String name) {
        return request.request(name);
    }

}

/**
 * 功能:
 * <p>公共接口, 抽象出代理方法, 可以实现面向接口编程时新增一个类而不改动老代码.</p>
 * 说明:
 * <pre>
 *     1. 思考这里需要联系多态.
 * </pre>
 */
interface MyHttpRequest {

    /**
     * 功能:
     * <p>模拟发起请求, 内部进行访问数据库</p>
     */
    public List<String> request(String name);

}

/**
 * 原始对象
 */
class Request implements MyHttpRequest {

    @Override
    public List<String> request(String name) {
        System.out.println("访问数据库...");
        List<String> result = Arrays.asList("s1", "s2", "s3");
        System.out.println("访问数据库完毕..., 查询参数为: " + name);
        return result;
    }

}

/**
 * 代理对象
 */
class RequestProxy implements MyHttpRequest {

    /**
     * 过滤正则
     */
    private static final Pattern reg = Pattern.compile(new String("or|and"));

    /**
     * 代理对象
     */
    private final Request request;

    public RequestProxy(Request request) {
        this.request = request;
    }

    /**
     * 执行参数过滤
     */
    public String preRequest(String param) {
        Matcher matcher = reg.matcher(param);
        if ( matcher.find() ) {
            System.out.println("参数不合法, 进行过滤");
            return param.substring(0, matcher.start());
        }
        return param;
    }

    /**
     * 代理方法
     */
    @Override
    public List<String> request(String name) {
        String preName = preRequest(name);
        List<String> requestRes = this.request.request(preName);
        return postRequest(requestRes);
    }

    /**
     * 执行请求完毕的后处理.
     */
    public List<String> postRequest(List<String> result) {
        System.out.println("结果过滤, 只返回前两条");
        return result.stream().limit(2).collect(Collectors.toList());
    }
}